#include "lcd.h"
#include "lcd_font.h"
#include "string.h"

void lcd_wr_reg(volatile uint16_t address)
{
    // 写入地址的寄存器
    *(volatile uint16_t *)(0x6C000000) = address; // 假设地址寄存器位于此地址
}

void lcd_wr_data(volatile uint16_t data)
{
    // 写入数据的寄存器
    *(volatile uint16_t *)(0x6C000800) = data; // 假设数据寄存器位于此地址
}

uint16_t lcd_rd_data()
{
    volatile uint16_t data = *(uint16_t *)(0x6c000800);
    return data;
}

void lcd_9341_init()
{
    /*打开屏幕背光*/
    HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_SET);

    /*厂家初始化代码*/
    lcd_wr_reg(0xCF);
    lcd_wr_data(0x00);
    lcd_wr_data(0xC1);
    lcd_wr_data(0X30);
    lcd_wr_reg(0xED);
    lcd_wr_data(0x64);
    lcd_wr_data(0x03);
    lcd_wr_data(0X12);
    lcd_wr_data(0X81);
    lcd_wr_reg(0xE8);
    lcd_wr_data(0x85);
    lcd_wr_data(0x10);
    lcd_wr_data(0x7A);
    lcd_wr_reg(0xCB);
    lcd_wr_data(0x39);
    lcd_wr_data(0x2C);
    lcd_wr_data(0x00);
    lcd_wr_data(0x34);
    lcd_wr_data(0x02);
    lcd_wr_reg(0xF7);
    lcd_wr_data(0x20);
    lcd_wr_reg(0xEA);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_reg(0xC0);  // Power control
    lcd_wr_data(0x1B); // VRH[5:0]
    lcd_wr_reg(0xC1);  // Power control
    lcd_wr_data(0x01); // SAP[2:0];BT[3:0]
    lcd_wr_reg(0xC5);  // VCM control
    lcd_wr_data(0x30); // 3F
    lcd_wr_data(0x30); // 3C
    lcd_wr_reg(0xC7);  // VCM control2
    lcd_wr_data(0XB7);
    lcd_wr_reg(0x36); // Memory Access Control
    lcd_wr_data(0x48);
    lcd_wr_reg(0x3A);
    lcd_wr_data(0x55);
    lcd_wr_reg(0xB1);
    lcd_wr_data(0x00);
    lcd_wr_data(0x1A);
    lcd_wr_reg(0xB6); // Display Function Control
    lcd_wr_data(0x0A);
    lcd_wr_data(0xA2);
    lcd_wr_reg(0xF2); // 3Gamma Function Disable
    lcd_wr_data(0x00);
    lcd_wr_reg(0x26); // Gamma curve selected
    lcd_wr_data(0x01);
    lcd_wr_reg(0xE0); // Set Gamma
    lcd_wr_data(0x0F);
    lcd_wr_data(0x2A);
    lcd_wr_data(0x28);
    lcd_wr_data(0x08);
    lcd_wr_data(0x0E);
    lcd_wr_data(0x08);
    lcd_wr_data(0x54);
    lcd_wr_data(0XA9);
    lcd_wr_data(0x43);
    lcd_wr_data(0x0A);
    lcd_wr_data(0x0F);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_reg(0XE1); // Set Gamma
    lcd_wr_data(0x00);
    lcd_wr_data(0x15);
    lcd_wr_data(0x17);
    lcd_wr_data(0x07);
    lcd_wr_data(0x11);
    lcd_wr_data(0x06);
    lcd_wr_data(0x2B);
    lcd_wr_data(0x56);
    lcd_wr_data(0x3C);
    lcd_wr_data(0x05);
    lcd_wr_data(0x10);
    lcd_wr_data(0x0F);
    lcd_wr_data(0x3F);
    lcd_wr_data(0x3F);
    lcd_wr_data(0x0F);
    lcd_wr_reg(0x2B);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_data(0x01);
    lcd_wr_data(0x3f);
    lcd_wr_reg(0x2A);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_data(0x00);
    lcd_wr_data(0xef);
    lcd_wr_reg(0x11); // Exit Sleep
    HAL_Delay(120);
    lcd_wr_reg(0x29); // display on

    /*用户初始化代码*/
    /*设置扫描方向*/
    lcd_wr_reg(0x36);
    lcd_wr_data(1 << 3);
    /*设置x和y的窗口大小*/
    lcd_wr_reg(0x2A);
    lcd_wr_data(0);
    lcd_wr_data(0);
    lcd_wr_data(239 >> 8);
    lcd_wr_data(239 & 0xFF);
    lcd_wr_reg(0x2B);
    lcd_wr_data(0);
    lcd_wr_data(0);
    lcd_wr_data(319 >> 8);
    lcd_wr_data(319 & 0xFF);
    /*清空屏幕*/
    lcd_clear(0x0000);
#if 0
  /*尝试读取控制芯片的ID*/
  lcd_wr_reg(0xD3);
  uint8_t d0 = lcd_rd_data();
  uint8_t d1 = lcd_rd_data();
  uint8_t d2 = lcd_rd_data();
  uint8_t d3 = lcd_rd_data();
  printf("%02X,%02X,%02X,%02X\n", d0, d1, d2, d3);
#endif
}

void lcd_set_cursor(uint16_t x, uint16_t y)
{
    lcd_wr_reg(0x2A); // 设置x
    lcd_wr_data(x >> 8);
    lcd_wr_data(x & 0xFF);
    lcd_wr_reg(0x2B); // 设置y
    lcd_wr_data(y >> 8);
    lcd_wr_data(y & 0xFF);
}

void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
    /*设置坐标*/
    lcd_set_cursor(x, y);

    /*准备写入GRAM*/
    lcd_wr_reg(0x2C);

    /*写入颜色*/
    lcd_wr_data(color);
}

uint16_t lcd_read_point(uint16_t x, uint16_t y)
{
    uint16_t r = 0, g = 0, b = 0;
    lcd_set_cursor(x, y);
    lcd_wr_reg(0x2E);
    r = lcd_rd_data(); // 假读
    r = lcd_rd_data(); // 读rg
    b = lcd_rd_data(); // 读b
    g = r & 0xFF;
    return ((r >> 11) << 11) | ((g >> 2) << 5) | (b >> 11);
}

void lcd_clear(uint16_t color)
{
    /*设置坐标*/
    lcd_set_cursor(0, 0);

    /*准备写入GRAM*/
    lcd_wr_reg(0x2C);

    /*写入颜色*/
    for (int i = 0; i < 320 * 240; i++)
    {
        lcd_wr_data(color);
    }
}

void lcd_show_char(uint16_t x, uint16_t y, char chr, uint16_t color)
{
    chr -= ' '; // 定位到字库中的下标
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            if ((lcd_font[chr][i] & (0x80 >> j)) != 0)
            {
                lcd_draw_point(x + j, y + i, color);
            }
            else
            {
                lcd_draw_point(x + j, y + i, 0x0000);
            }
        }
    }
}

void lcd_show_string(uint16_t x, uint16_t y, char *buffer, uint16_t color)
{
    uint16_t len = strlen(buffer);
    uint16_t pos_x = x;
    uint16_t pos_y = y;
    for (int i = 0; i < len; i++)
    {
        if (buffer[i] == '\n')
        {
            x = pos_x;
            y += 16;
            continue;
        }
        lcd_show_char(x, y, buffer[i], color);
        x += 8;
        if ((240 - x) < 8)
        {
            break; // 超出屏幕范围，跳出函数
        }
    }
}

void lcd_draw_cross(uint16_t x, uint16_t y, uint16_t length, uint16_t color)
{
    for (int i = 0; i < length; i++)
    {
        lcd_draw_point(x - length / 2 + i, y, color);
        lcd_draw_point(x, y - length / 2 + i, color);
    }
}
